/* eslint-disable @typescript-eslint/no-explicit-any */
import axios, { Method } from 'axios';
import { Toast } from 'antd-mobile';
import { baseURL } from 'config/porxy';

import qs from 'qs';
import { history } from 'umi';
import Var from '@/setting';

/**
 * ===============================================================================
 *  pont_requestType对应的字典表，可自行添加对应的key和value
 * ===============================================================================
 */
enum CONTENT_TYPE {
  json = 'application/json',
  form = 'application/x-www-form-urlencoded; charset=utf-8',
  file = 'multipart/form-data',
}

enum paramsName {
  GET = 'params',
  get = 'params',
  POST = 'data',
  post = 'data',
}
/**
 * ===============================================================================
 *  请求方法定义
 *  需要改变content-type值就在payload中添加对应属性：
 *    payload.pont_requestType = 'json'
 * ===============================================================================
 */
const instance = axios.create({
  baseURL,
  timeout: 10000,
  withCredentials: true, // 请求带cookie需要该设置
  headers: { 'Content-type': 'application/x-www-form-urlencoded; charset=utf-8' },
});

export default (url: string, payload: any, method: Method) => {
  // fix: 检查网络情况
  if (!window.navigator.onLine) {
    Toast.show({
      icon: 'fail',
      content: '网络连接失败',
    });
    return;
  }

  // fix:当为默认content-type时需要初始化参数
  let result = qs.stringify(payload);
  let headers = {};
  // 获取其他配置信息
  const options = payload?.pont_options;
  // 获取自定义请求头信息
  if (payload?.pont_requestType) {
    // 是否序列化请求体
    result = payload;
    headers = { 'Content-type': CONTENT_TYPE[payload.pont_requestType as keyof typeof CONTENT_TYPE] };
  }
  // 删除请求中的axios配置字段
  delete payload?.pont_requestType;
  delete payload?.pont_options;

  return instance({
    url,
    method,
    [paramsName[method as keyof typeof paramsName]]: result,
    /** 自定义请求头信息 */
    headers,
    /** 覆盖所有默认配置：url、method、data */
    ...options,
  });
};

/**
 * ===============================================================================
 *  请求拦截
 *  在请求发出前可以对请求进行自定义操作
 * ===============================================================================
 */
instance.interceptors.request.use(
  (config) => {
    return config;
  },
  (error) => Promise.reject(error),
);

/**
 * ===============================================================================
 *  响应拦截
 *  接收到响应后对响应数据进行自定义操作
 * ===============================================================================
 */
instance.interceptors.response.use(
  (response) => {
    if (!response?.data) {
      Toast.show({
        icon: 'fail',
        content: '数据响应为空！',
      });
      return;
    }
    // 登录状态过期
    if (response?.data?.code === Var.reLoginCode && !history?.location?.pathname?.includes('login')) {
      Toast.show({
        icon: 'fail',
        content: '登录状态已过期，请重新登录',
      });
      window.sessionStorage.clear();
      history.push('/');
      return;
    }
    // 数据响应code不正常
    if (response?.data?.code !== 200) {
      Toast.show({
        icon: 'fail',
        content: `数据响应失败，${response?.data?.code}:${response?.data?.message || '请联系管理员'}`,
      });
    }
    // 数据返回一切正常
    return response.data;
  },
  (error) => {
    if (!error.response) {
      Toast.show({
        icon: 'fail',
        content: '请求错误 - 请联系管理员',
      });
      throw new Error(error);
    }
  },
);
